/**
 * Hellotxt AS3 API
 * For more information: http://code.google.com/p/hellotxt-as3/
 * This script is based on the great twitter API TwitterScript (http://code.google.com/p/twitterscript/)
 * 
 * P.S. version date format: dd/mm/yyyy
 * 
 * @author	Lucas Araujo <araujo.lucas [at] gmail.com> - http://hellotxt.com/user/lucas
 * @version	0.1 9/2/2009 22:00
 */
package hellotxt.api
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLRequestHeader;
	import flash.net.URLVariables;

	import hellotxt.api.events.HellotxtEvent;
	import hellotxt.api.data.HellotxtMessage;
	
	/**
	 * 
	 */
	public class Hellotxt extends EventDispatcher
	{
		// constants used for loaders
		protected static const VALIDATE:String = "validate";
		protected static const USER_POST:String = "userPost";
		protected static const USER_SERVICES:String = "userServices";
		protected static const USER_LATEST:String = "userLatest";
		
		//
		protected var app_key:String;
		
		//
		protected var user_key:String;

		// Use secure connection?
		protected var useHttps:Boolean = false;

		// Last url used (for debug only)
		public var lastURL:String;
		
		
		// internal variables
		
		// URLLoders
		protected var loaders:Array;
		
		// API URL
		protected var hellotxtAPIUrl:String = "http://hellotxt.com/api/v1/method/";
	
		/**
		 * Hellotxt
		 * 
		 * Usage:
		 * <code>
		 *   var hellotxt:Hellotxt = new Hellotxt("app_key", "user_key");
		 *   hellotxt.addEventListener(HellotxtEvent.ON_USER_LATEST_RESULT, latestHandler);
		 *   hellotxt.addEventListener(HellotxtEvent.ON_ERROR, errorHandler);
		 *   hellotxt.userLatest();
		 * </code>
		 * 
		 * @param	app_key
		 * @param	user_key
		 */
		public function Hellotxt(app_key:String=null, user_key:String=null):void
		{
			this.setAuthentication(app_key, user_key);
		}

		/**
		 * 
		 * @param	app_key
		 * @param	user_key
		 */
		public function setAuthentication(app_key:String, user_key:String):void
		{
			if (null != app_key && null != user_key)
			{
				this.app_key = app_key;
				this.user_key = user_key;
			}
		}

		public function userValidate():void
		{
			var loader:URLLoader = this.getLoader(VALIDATE);
			var request:URLRequest = this.hellotxtRequest("user.validate");
			loader.load(request);
		}

		/**
		 * 
		 * @param	message
		 * @param	debug
		 */
		public function userPost(message:*, debug:Boolean=false):void
		{
			throw new Error("Not implemented yet");
		}

		public function userServices():void
		{
			var loader:URLLoader = this.getLoader(USER_SERVICES);
			var request:URLRequest = this.hellotxtRequest("user.services");
			loader.load(request);			
		}

		public function userLatest():void
		{
			var loader:URLLoader = this.getLoader(USER_LATEST);
			var request:URLRequest = this.hellotxtRequest("user.latest");
			loader.load(request);			
		}
		
		
		// Protected Handlers
		
		protected function validateHandler(e:Event):void
		{
			this.defaultHandler(VALIDATE, HellotxtEvent.ON_VALIDATE_RESULT);
		}
		
		protected function userPostHandler(e:Event):void
		{
			this.defaultHandler(USER_POST, HellotxtEvent.ON_USER_POST_RESULT);
		}
		
		protected function userServicesHandler(e:Event):void
		{
			this.defaultHandler(USER_SERVICES, HellotxtEvent.ON_USER_SERVICES_RESULT);
		}
		
		protected function userLatestHandler(e:Event):void
		{
			this.defaultHandler(USER_LATEST, HellotxtEvent.ON_USER_LATEST_RESULT);
		}
		
		
		// protected helper handlers
		
		/**
		 * This method dipatch a new HellotxtEvent 
		 * 
		 * @param	errorEvent
		 */
		protected function errorHandler(errorEvent:IOErrorEvent):void
		{
			var t:HellotxtEvent = new HellotxtEvent(HellotxtEvent.ON_ERROR);
			t.data = errorEvent.text;
			this.dispatchEvent(t);
		}
		
		/**
		 * Default Handler
		 * 
		 * @param	loaderName
		 * @param	eventName
		 */
		protected function defaultHandler(loaderName:String, eventName:String):void
		{
			var data:String = this.getLoader(loaderName).data;
			var result:HellotxtEvent = new HellotxtEvent(eventName);
			result.data = data;
			this.dispatchEvent(result);
		}			
		
		// protected helper methods
		
		/**
		 * 
		 * @param	name
		 * @param	completeHandler
		 */
		protected function addLoader(name:String, completeHandler:Function):void
		{
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, completeHandler);
			loader.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
			loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorHandler);
			this.loaders[name] = loader;
		}

		/**
		 * 
		 * @param	name
		 * @return
		 */
		protected function getLoader(name:String):URLLoader
		{
			if (this.loaders == null)
			{
				this.loaders = [];
				this.addLoader(VALIDATE, validateHandler);
				this.addLoader(USER_POST, userPostHandler);
				this.addLoader(USER_SERVICES, userServicesHandler);
				this.addLoader(USER_LATEST, userLatestHandler);
			}
			return this.loaders[name] as URLLoader;
		}
		
		/**
		 * 
		 * @param	url_args
		 * @return	A query string from url_args
		 */
		protected function getQueryString(url_args:Object = null):String
		{
			var pairs:Array = [];
			for (var i:String in url_args)
				if (url_args[i])
					pairs.push(i + "=" + url_args[i]);			
			if (pairs.length)
				return "?" + pairs.join("&");
			return "";
		}
		
		/**
		 * 
		 * @param	uri
		 * @param	url_args
		 * @return	An URL
		 */
		protected function getUrl(uri:String, url_args:Object = null):String
		{
			var query:String = this.getQueryString(url_args);
			var url:String = this.hellotxtAPIUrl + uri + query;
			if (this.useHttps)
				url = url.replace("http://", "https://");
			return url;
		}
		
		/**
		 * 
		 * @param	uri
		 * @param	url_args
		 * @param	post_args
		 * @return	URLRequest
		 */
		protected function hellotxtRequest(uri:String, url_args:Object=null, post_args:URLVariables=null):URLRequest
		{
			var url:String = this.getUrl(uri, url_args);
			var request:URLRequest = new URLRequest(url);
			this.lastURL = url;

			if (post_args == null)
				post_args = new URLVariables();
			if (this.app_key)
				post_args.app_key = this.app_key;
			if (this.user_key)
				post_args.user_key = this.user_key;
			
			request.method = URLRequestMethod.POST;
			request.data = post_args;
			return request;
		}
	}
}